/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 *                                                                       *
 *   JavaWorld Library, Copyright 2011 Bryan Chadwick                    *
 *                                                                       *
 *   FILE: ./hidden/WebPage.java                                         *
 *                                                                       *
 *   This file is part of JavaWorld.                                     *
 *                                                                       *
 *   JavaWorld is free software: you can redistribute it and/or          *
 *   modify it under the terms of the GNU General Public License         *
 *   as published by the Free Software Foundation, either version        *
 *   3 of the License, or (at your option) any later version.            *
 *                                                                       *
 *   JavaWorld is distributed in the hope that it will be useful,        *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of      *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       *
 *   GNU General Public License for more details.                        *
 *                                                                       *
 *   You should have received a copy of the GNU General Public License   *
 *   along with JavaWorld.  If not, see <http://www.gnu.org/licenses/>.  *
 *                                                                       *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

package hidden;

import image.*;
import world.*;

/** Images for the JavaWorld homepage */
public class WebPage{
    WebPage(){}

    public static void main(String[] args){
        WebPage wp = new WebPage();
        
        ALoD start = new ConsLoD(new Right(), new MtLoD());
        wp.jurassic(11, start).draw(new Posn(180, 40), 100, new EmptyScene(230, 180))
                .toFile("imagetutor/images/jurassic.png");
                
        wp.circles(45, 50, Math.PI/12, 60, 60, new EmptyScene(155, 165))
                .toFile("imagetutor/images/spiral.png");
        
        wp.koch(6, 240, 0, 10, 80, new EmptyScene(260, 90))
                .toFile("imagetutor/images/koch.png");
    }
 
    Scene koch(int iter, double len, double ang, double x, double y, Scene scn){
        double next = len/3;
        if(iter <= 1){
            return scn.addLine(x, y, x+Math.cos(ang)*(len), y-Math.sin(ang)*(len), "red");
        }else{
            return this.koch(iter-1, next, ang, x, y,
                     this.koch(iter-1, next, ang+Math.PI/3, x+Math.cos(ang)*next, y-Math.sin(ang)*next,
                       this.koch(iter-1, next, ang-Math.PI/3,
                               x+Math.cos(ang)*next+Math.cos(ang+Math.PI/3)*next,
                               y-Math.sin(ang)*next-Math.sin(ang+Math.PI/3)*next,
                         this.koch(iter-1, next, ang, x+Math.cos(ang)*2*next, y-Math.sin(ang)*2*next, scn))));
        }
    }
    
    Scene circles(int iter, double size, double ang, double x, double y, Scene scn){
        double next = size;//7*size/8;
        if(size <= 2 || iter <= 0){
            return scn;
        }else{
            Image what = new Overlay(new Circle(size, "outline", "navy"),
                                     new Circle(size, "solid", "lightgrey"));
            return this.circles(iter-1, next-1,
                                ang-Math.PI/12,
                                x+Math.cos(ang)*8,
                                y-Math.sin(ang)*8,
                                scn.placeImage(what, x, y));
        }
    }
    
    ALoD jurassic(int iter, ALoD dirs){
        if(iter <= 0){
            return dirs;
        }else{
            return this.jurassic(iter-1, dirs.revRotate(dirs));
        }
    } 
    
    static abstract class Dir{
        static int SIZE = 3;
        abstract Dir rotate();
        abstract Posn next(Posn p);
    }
    static class Up extends Dir{
        Up(){}
        Dir rotate(){ return new Right(); }
        Posn next(Posn p){ return new Posn(p.x, p.y-SIZE); }
    }
    static class Down extends Dir{
        Down(){}
        Dir rotate(){ return new Left(); }
        Posn next(Posn p){ return new Posn(p.x, p.y+SIZE); }
    }
    static class Left extends Dir{
        Left(){}
        Dir rotate(){ return new Up(); }
        Posn next(Posn p){ return new Posn(p.x-SIZE, p.y); }
    }
    static class Right extends Dir{
        Right(){}
        Dir rotate(){ return new Down(); }
        Posn next(Posn p){ return new Posn(p.x+SIZE, p.y); }
    }
    static abstract class ALoD{
        ALoD(){}
        abstract ALoD revRotate(ALoD acc);
        abstract Scene draw(Posn from, int color, Scene scn);
    }
    static class MtLoD extends ALoD{
        MtLoD(){}
        ALoD revRotate(ALoD acc){ return acc; }
        Scene draw(Posn from, int color, Scene scn){ return scn; }
    }
    static class ConsLoD extends ALoD{
        Dir first;
        ALoD rest;
        ConsLoD(Dir first, ALoD rest){
            this.first = first;
            this.rest = rest;
        }
        ALoD revRotate(ALoD acc){
            return this.rest.revRotate(new ConsLoD(this.first.rotate(), acc));    
        }
        Scene draw(Posn from, int color, Scene scn){
            Posn next = this.first.next(from);
            return this.rest.draw(next, color+30030,
                    scn.addLine(from, next, ColorDatabase.makeColor(color)));
        }
    }
}

